<!DOCTYPE html>
<html lang="en">
<head>
    
    <meta charset="utf-8">
    <title>src/deprecated/from_html.js - Documentation</title>
    
    
    <script src="scripts/prettify/prettify.js"></script>
    <script src="scripts/prettify/lang-css.js"></script>
    <!--[if lt IE 9]>
      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    <link type="text/css" rel="stylesheet" href="styles/prettify.css">
    <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>

<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
  <div class="navicon"></div>
</label>

<label for="nav-trigger" class="overlay"></label>

<nav >
    
    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="-_anonymous_-jsPDF-API.GState.html">GState</a></li><li><a href="-_anonymous_-jsPDF-API.ShadingPattern.html">ShadingPattern</a></li><li><a href="-_anonymous_-jsPDF-API.TilingPattern.html">TilingPattern</a></li><li><a href="GState.html">GState</a></li><li><a href="jsPDF.html">jsPDF</a><ul class='methods'><li data-type='method'><a href="jsPDF.html#addFont">addFont</a></li><li data-type='method'><a href="jsPDF.html#addGState">addGState</a></li><li data-type='method'><a href="jsPDF.html#addPage">addPage</a></li><li data-type='method'><a href="jsPDF.html#addPattern">addPattern</a></li><li data-type='method'><a href="jsPDF.html#beginFormObject">beginFormObject</a></li><li data-type='method'><a href="jsPDF.html#circle">circle</a></li><li data-type='method'><a href="jsPDF.html#clip">clip</a></li><li data-type='method'><a href="jsPDF.html#clipEvenOdd">clipEvenOdd</a></li><li data-type='method'><a href="jsPDF.html#close">close</a></li><li data-type='method'><a href="jsPDF.html#comment">comment</a></li><li data-type='method'><a href="jsPDF.html#curveTo">curveTo</a></li><li data-type='method'><a href="jsPDF.html#deletePage">deletePage</a></li><li data-type='method'><a href="jsPDF.html#discardPath">discardPath</a></li><li data-type='method'><a href="jsPDF.html#doFormObject">doFormObject</a></li><li data-type='method'><a href="jsPDF.html#ellipse">ellipse</a></li><li data-type='method'><a href="jsPDF.html#endFormObject">endFormObject</a></li><li data-type='method'><a href="jsPDF.html#fill">fill</a></li><li data-type='method'><a href="jsPDF.html#fillEvenOdd">fillEvenOdd</a></li><li data-type='method'><a href="jsPDF.html#fillStroke">fillStroke</a></li><li data-type='method'><a href="jsPDF.html#fillStrokeEvenOdd">fillStrokeEvenOdd</a></li><li data-type='method'><a href="jsPDF.html#getCharSpace">getCharSpace</a></li><li data-type='method'><a href="jsPDF.html#getCreationDate">getCreationDate</a></li><li data-type='method'><a href="jsPDF.html#getDrawColor">getDrawColor</a></li><li data-type='method'><a href="jsPDF.html#getFileId">getFileId</a></li><li data-type='method'><a href="jsPDF.html#getFillColor">getFillColor</a></li><li data-type='method'><a href="jsPDF.html#getFont">getFont</a></li><li data-type='method'><a href="jsPDF.html#getFontList">getFontList</a></li><li data-type='method'><a href="jsPDF.html#getFontSize">getFontSize</a></li><li data-type='method'><a href="jsPDF.html#getFormObject">getFormObject</a></li><li data-type='method'><a href="jsPDF.html#getLineHeightFactor">getLineHeightFactor</a></li><li data-type='method'><a href="jsPDF.html#getR2L">getR2L</a></li><li data-type='method'><a href="jsPDF.html#getTextColor">getTextColor</a></li><li data-type='method'><a href="jsPDF.html#insertPage">insertPage</a></li><li data-type='method'><a href="jsPDF.html#line">line</a></li><li data-type='method'><a href="jsPDF.html#lines">lines</a></li><li data-type='method'><a href="jsPDF.html#lineTo">lineTo</a></li><li data-type='method'><a href="jsPDF.html#lstext">lstext</a></li><li data-type='method'><a href="jsPDF.html#movePage">movePage</a></li><li data-type='method'><a href="jsPDF.html#moveTo">moveTo</a></li><li data-type='method'><a href="jsPDF.html#output">output</a></li><li data-type='method'><a href="jsPDF.html#path">path</a></li><li data-type='method'><a href="jsPDF.html#rect">rect</a></li><li data-type='method'><a href="jsPDF.html#restoreGraphicsState">restoreGraphicsState</a></li><li data-type='method'><a href="jsPDF.html#roundedRect">roundedRect</a></li><li data-type='method'><a href="jsPDF.html#save">save</a></li><li data-type='method'><a href="jsPDF.html#saveGraphicsState">saveGraphicsState</a></li><li data-type='method'><a href="jsPDF.html#setCharSpace">setCharSpace</a></li><li data-type='method'><a href="jsPDF.html#setCreationDate">setCreationDate</a></li><li data-type='method'><a href="jsPDF.html#setCurrentTransformationMatrix">setCurrentTransformationMatrix</a></li><li data-type='method'><a href="jsPDF.html#setDisplayMode">setDisplayMode</a></li><li data-type='method'><a href="jsPDF.html#setDocumentProperties">setDocumentProperties</a></li><li data-type='method'><a href="jsPDF.html#setDrawColor">setDrawColor</a></li><li data-type='method'><a href="jsPDF.html#setFileId">setFileId</a></li><li data-type='method'><a href="jsPDF.html#setFillColor">setFillColor</a></li><li data-type='method'><a href="jsPDF.html#setFont">setFont</a></li><li data-type='method'><a href="jsPDF.html#setFontSize">setFontSize</a></li><li data-type='method'><a href="jsPDF.html#setFontStyle">setFontStyle</a></li><li data-type='method'><a href="jsPDF.html#setGState">setGState</a></li><li data-type='method'><a href="jsPDF.html#setLineCap">setLineCap</a></li><li data-type='method'><a href="jsPDF.html#setLineDashPattern">setLineDashPattern</a></li><li data-type='method'><a href="jsPDF.html#setLineHeightFactor">setLineHeightFactor</a></li><li data-type='method'><a href="jsPDF.html#setLineJoin">setLineJoin</a></li><li data-type='method'><a href="jsPDF.html#setLineMiterLimit">setLineMiterLimit</a></li><li data-type='method'><a href="jsPDF.html#setLineWidth">setLineWidth</a></li><li data-type='method'><a href="jsPDF.html#setPage">setPage</a></li><li data-type='method'><a href="jsPDF.html#setPrecision">setPrecision</a></li><li data-type='method'><a href="jsPDF.html#setR2L">setR2L</a></li><li data-type='method'><a href="jsPDF.html#setTextColor">setTextColor</a></li><li data-type='method'><a href="jsPDF.html#stroke">stroke</a></li><li data-type='method'><a href="jsPDF.html#text">text</a></li><li data-type='method'><a href="jsPDF.html#triangle">triangle</a></li></ul></li><li><a href="Matrix.html">Matrix</a><ul class='methods'><li data-type='method'><a href="Matrix.html#applyToPoint">applyToPoint</a></li><li data-type='method'><a href="Matrix.html#applyToRectangle">applyToRectangle</a></li><li data-type='method'><a href="Matrix.html#clone">clone</a></li><li data-type='method'><a href="Matrix.html#decompose">decompose</a></li><li data-type='method'><a href="Matrix.html#inversed">inversed</a></li><li data-type='method'><a href="Matrix.html#join">join</a></li><li data-type='method'><a href="Matrix.html#multiply">multiply</a></li><li data-type='method'><a href="Matrix.html#toString">toString</a></li></ul></li><li><a href="module-AcroForm-AcroFormButton.html">AcroFormButton</a></li><li><a href="module-AcroForm-AcroFormCheckBox.html">AcroFormCheckBox</a></li><li><a href="module-AcroForm-AcroFormChoiceField.html">AcroFormChoiceField</a></li><li><a href="module-AcroForm-AcroFormComboBox.html">AcroFormComboBox</a><ul class='methods'><li data-type='method'><a href="module-AcroForm-AcroFormComboBox.html#addOption">addOption</a></li><li data-type='method'><a href="module-AcroForm-AcroFormComboBox.html#getOptions">getOptions</a></li><li data-type='method'><a href="module-AcroForm-AcroFormComboBox.html#removeOption">removeOption</a></li><li data-type='method'><a href="module-AcroForm-AcroFormComboBox.html#setOptions">setOptions</a></li></ul></li><li><a href="module-AcroForm-AcroFormEditBox.html">AcroFormEditBox</a><ul class='methods'><li data-type='method'><a href="module-AcroForm-AcroFormEditBox.html#addOption">addOption</a></li><li data-type='method'><a href="module-AcroForm-AcroFormEditBox.html#getOptions">getOptions</a></li><li data-type='method'><a href="module-AcroForm-AcroFormEditBox.html#removeOption">removeOption</a></li><li data-type='method'><a href="module-AcroForm-AcroFormEditBox.html#setOptions">setOptions</a></li></ul></li><li><a href="module-AcroForm-AcroFormField.html">AcroFormField</a></li><li><a href="module-AcroForm-AcroFormListBox.html">AcroFormListBox</a><ul class='methods'><li data-type='method'><a href="module-AcroForm-AcroFormListBox.html#addOption">addOption</a></li><li data-type='method'><a href="module-AcroForm-AcroFormListBox.html#getOptions">getOptions</a></li><li data-type='method'><a href="module-AcroForm-AcroFormListBox.html#removeOption">removeOption</a></li><li data-type='method'><a href="module-AcroForm-AcroFormListBox.html#setOptions">setOptions</a></li></ul></li><li><a href="module-AcroForm-AcroFormPasswordField.html">AcroFormPasswordField</a></li><li><a href="module-AcroForm-AcroFormPDFObject.html">AcroFormPDFObject</a></li><li><a href="module-AcroForm-AcroFormPushButton.html">AcroFormPushButton</a></li><li><a href="module-AcroForm-AcroFormRadioButton.html">AcroFormRadioButton</a></li><li><a href="module-AcroForm-AcroFormTextField.html">AcroFormTextField</a></li><li><a href="module-canvas-Canvas.html">Canvas</a></li></ul><h3>Modules</h3><ul><li><a href="module-AcroForm.html">AcroForm</a><ul class='methods'><li data-type='method'><a href="module-AcroForm.html#addButton">addButton</a></li><li data-type='method'><a href="module-AcroForm.html#addChoiceField">addChoiceField</a></li><li data-type='method'><a href="module-AcroForm.html#addField">addField</a></li><li data-type='method'><a href="module-AcroForm.html#addTextField">addTextField</a></li></ul></li><li><a href="module-addImage.html">addImage</a><ul class='methods'><li data-type='method'><a href="module-addImage.html#~addImage">addImage</a></li><li data-type='method'><a href="module-addImage.html#~arrayBufferToBinaryString">arrayBufferToBinaryString</a></li><li data-type='method'><a href="module-addImage.html#~binaryStringToUint8Array">binaryStringToUint8Array</a></li><li data-type='method'><a href="module-addImage.html#~convertBase64ToBinaryString">convertBase64ToBinaryString</a></li><li data-type='method'><a href="module-addImage.html#~extractImageFromDataUrl">extractImageFromDataUrl</a></li><li data-type='method'><a href="module-addImage.html#~getImageFileTypeByImageData">getImageFileTypeByImageData</a></li><li data-type='method'><a href="module-addImage.html#~getImageProperties">getImageProperties</a></li><li data-type='method'><a href="module-addImage.html#~isArrayBuffer">isArrayBuffer</a></li><li data-type='method'><a href="module-addImage.html#~isArrayBufferView">isArrayBufferView</a></li><li data-type='method'><a href="module-addImage.html#~sHashCode">sHashCode</a></li><li data-type='method'><a href="module-addImage.html#~supportsArrayBuffer">supportsArrayBuffer</a></li><li data-type='method'><a href="module-addImage.html#~validateStringAsBase64">validateStringAsBase64</a></li></ul></li><li><a href="module-annotations.html">annotations</a><ul class='methods'><li data-type='method'><a href="module-annotations.html#~createAnnotation">createAnnotation</a></li><li data-type='method'><a href="module-annotations.html#~getTextWidth">getTextWidth</a></li><li data-type='method'><a href="module-annotations.html#~link">link</a></li><li data-type='method'><a href="module-annotations.html#~textWithLink">textWithLink</a></li></ul></li><li><a href="module-arabic.html">arabic</a><ul class='methods'><li data-type='method'><a href="module-arabic.html#~processArabic">processArabic</a></li></ul></li><li><a href="module-autoprint.html">autoprint</a><ul class='methods'><li data-type='method'><a href="module-autoprint.html#~autoPrint">autoPrint</a></li></ul></li><li><a href="module-bmp_support.html">bmp_support</a></li><li><a href="module-canvas.html">canvas</a><ul class='methods'><li data-type='method'><a href="module-canvas.html#~getContext">getContext</a></li><li data-type='method'><a href="module-canvas.html#~toDataURL">toDataURL</a></li></ul></li><li><a href="module-cell.html">cell</a><ul class='methods'><li data-type='method'><a href="module-cell.html#~cell">cell</a></li><li data-type='method'><a href="module-cell.html#~cellAddPage">cellAddPage</a></li><li data-type='method'><a href="module-cell.html#~cellInitialize">cellInitialize</a></li><li data-type='method'><a href="module-cell.html#~getTextDimensions">getTextDimensions</a></li><li data-type='method'><a href="module-cell.html#~printHeaderRow">printHeaderRow</a></li><li data-type='method'><a href="module-cell.html#~setHeaderFunction">setHeaderFunction</a></li><li data-type='method'><a href="module-cell.html#~setTableHeaderRow">setTableHeaderRow</a></li><li data-type='method'><a href="module-cell.html#~table">table</a></li></ul></li><li><a href="module-context2d.html">context2d</a><ul class='methods'><li data-type='method'><a href="module-context2d.html#~arc">arc</a></li><li data-type='method'><a href="module-context2d.html#~arcTo">arcTo</a></li><li data-type='method'><a href="module-context2d.html#~beginPath">beginPath</a></li><li data-type='method'><a href="module-context2d.html#~bezierCurveTo">bezierCurveTo</a></li><li data-type='method'><a href="module-context2d.html#~clearRect">clearRect</a></li><li data-type='method'><a href="module-context2d.html#~clip">clip</a></li><li data-type='method'><a href="module-context2d.html#~closePath">closePath</a></li><li data-type='method'><a href="module-context2d.html#~createArc">createArc</a></li><li data-type='method'><a href="module-context2d.html#~fillRect">fillRect</a></li><li data-type='method'><a href="module-context2d.html#~fillText">fillText</a></li><li data-type='method'><a href="module-context2d.html#~lineTo">lineTo</a></li><li data-type='method'><a href="module-context2d.html#~measureText">measureText</a></li><li data-type='method'><a href="module-context2d.html#~moveTo">moveTo</a></li><li data-type='method'><a href="module-context2d.html#~quadraticCurveTo">quadraticCurveTo</a></li><li data-type='method'><a href="module-context2d.html#~rect">rect</a></li><li data-type='method'><a href="module-context2d.html#~restore">restore</a></li><li data-type='method'><a href="module-context2d.html#~rotate">rotate</a></li><li data-type='method'><a href="module-context2d.html#~save">save</a></li><li data-type='method'><a href="module-context2d.html#~scale">scale</a></li><li data-type='method'><a href="module-context2d.html#~setTransform">setTransform</a></li><li data-type='method'><a href="module-context2d.html#~stroke">stroke</a></li><li data-type='method'><a href="module-context2d.html#~strokeRect">strokeRect</a></li><li data-type='method'><a href="module-context2d.html#~strokeText">strokeText</a></li><li data-type='method'><a href="module-context2d.html#~toDataURL">toDataURL</a></li><li data-type='method'><a href="module-context2d.html#~transform">transform</a></li><li data-type='method'><a href="module-context2d.html#~translate">translate</a></li></ul></li><li><a href="module-fileloading.html">fileloading</a><ul class='methods'><li data-type='method'><a href="module-fileloading.html#~loadFile">loadFile</a></li><li data-type='method'><a href="module-fileloading.html#~loadImageFile">loadImageFile</a></li></ul></li><li><a href="module-gif_support.html">gif_support</a></li><li><a href="module-html.html">html</a><ul class='methods'><li data-type='method'><a href="module-html.html#~html">html</a></li></ul></li><li><a href="module-javascript.html">javascript</a><ul class='methods'><li data-type='method'><a href="module-javascript.html#~addJS">addJS</a></li></ul></li><li><a href="module-jpeg_support.html">jpeg_support</a></li><li><a href="module-outline.html">outline</a></li><li><a href="module-png_support.html">png_support</a></li><li><a href="module-setLanguage.html">setLanguage</a><ul class='methods'><li data-type='method'><a href="module-setLanguage.html#~setLanguage">setLanguage</a></li></ul></li><li><a href="module-split_text_to_size.html">split_text_to_size</a><ul class='methods'><li data-type='method'><a href="module-split_text_to_size.html#~getCharWidthsArray">getCharWidthsArray</a></li><li data-type='method'><a href="module-split_text_to_size.html#~getStringUnitWidth">getStringUnitWidth</a></li><li data-type='method'><a href="module-split_text_to_size.html#~splitTextToSize">splitTextToSize</a></li></ul></li><li><a href="module-standard_fonts_metrics.html">standard_fonts_metrics</a></li><li><a href="module-svg.html">svg</a><ul class='methods'><li data-type='method'><a href="module-svg.html#~addSvg">addSvg</a></li><li data-type='method'><a href="module-svg.html#~addSvgAsImage">addSvgAsImage</a></li></ul></li><li><a href="module-total_pages.html">total_pages</a><ul class='methods'><li data-type='method'><a href="module-total_pages.html#~putTotalPages">putTotalPages</a></li></ul></li><li><a href="module-ttfsupport.html">ttfsupport</a></li><li><a href="module-utf8.html">utf8</a></li><li><a href="module-vFS.html">vFS</a><ul class='methods'><li data-type='method'><a href="module-vFS.html#~addFileToVFS">addFileToVFS</a></li><li data-type='method'><a href="module-vFS.html#~existsFileInVFS">existsFileInVFS</a></li><li data-type='method'><a href="module-vFS.html#~getFileFromVFS">getFileFromVFS</a></li></ul></li><li><a href="module-viewerpreferences.html">viewerpreferences</a><ul class='methods'><li data-type='method'><a href="module-viewerpreferences.html#~viewerPreferences">viewerPreferences</a></li></ul></li><li><a href="module-webp_support.html">webp_support</a></li><li><a href="module-xmp_metadata.html">xmp_metadata</a><ul class='methods'><li data-type='method'><a href="module-xmp_metadata.html#~addMetadata">addMetadata</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#addHTML">addHTML</a></li><li><a href="global.html#http">http</a></li><li><a href="global.html#promptUser">promptUser</a></li></ul>
</nav>

<div id="main">
    
    <h1 class="page-title">src/deprecated/from_html.js</h1>
    

    



    
    <section>
        <article>
            <pre class="prettyprint source linenums"><code>/**
 * jsPDF fromHTML plugin. BETA stage. API subject to change. Needs browser
 * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
 *               2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
 *               2014 Diego Casorran, https://github.com/diegocr
 *               2014 Daniel Husar, https://github.com/danielhusar
 *               2014 Wolfgang Gassler, https://github.com/woolfg
 *               2014 Steven Spungin, https://github.com/flamenco
 *
 * @license
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */

(function(jsPDFAPI) {
  var clone,
    DrillForContent,
    FontNameDB,
    FontStyleMap,
    TextAlignMap,
    FontWeightMap,
    FloatMap,
    ClearMap,
    GetCSS,
    PurgeWhiteSpace,
    Renderer,
    ResolveFont,
    ResolveUnitedNumber,
    UnitedNumberMap,
    elementHandledElsewhere,
    images,
    loadImgs,
    checkForFooter,
    process,
    tableToJson;
  clone = (function() {
    return function(obj) {
      Clone.prototype = obj;
      return new Clone();
    };
    function Clone() {}
  })();
  PurgeWhiteSpace = function(array) {
    var fragment, i, l, lTrimmed, r, rTrimmed, trailingSpace;
    i = 0;
    l = array.length;
    fragment = void 0;
    lTrimmed = false;
    rTrimmed = false;
    while (!lTrimmed &amp;&amp; i !== l) {
      fragment = array[i] = array[i].trimLeft();
      if (fragment) {
        lTrimmed = true;
      }
      i++;
    }
    i = l - 1;
    while (l &amp;&amp; !rTrimmed &amp;&amp; i !== -1) {
      fragment = array[i] = array[i].trimRight();
      if (fragment) {
        rTrimmed = true;
      }
      i--;
    }
    r = /\s+$/g;
    trailingSpace = true;
    i = 0;
    while (i !== l) {
      // Leave the line breaks intact
      if (array[i] != "\u2028") {
        fragment = array[i].replace(/\s+/g, " ");
        if (trailingSpace) {
          fragment = fragment.trimLeft();
        }
        if (fragment) {
          trailingSpace = r.test(fragment);
        }
        array[i] = fragment;
      }
      i++;
    }
    return array;
  };
  Renderer = function(pdf, x, y, settings) {
    this.pdf = pdf;
    this.x = x;
    this.y = y;
    this.settings = settings;
    //list of functions which are called after each element-rendering process
    this.watchFunctions = [];
    this.init();
    return this;
  };
  ResolveFont = function(css_font_family_string) {
    var name, part, parts;
    name = void 0;
    parts = css_font_family_string.split(",");
    part = parts.shift();
    while (!name &amp;&amp; part) {
      name = FontNameDB[part.trim().toLowerCase()];
      part = parts.shift();
    }
    return name;
  };
  ResolveUnitedNumber = function(css_line_height_string) {
    //IE8 issues
    css_line_height_string =
      css_line_height_string === "auto" ? "0px" : css_line_height_string;
    if (
      css_line_height_string.indexOf("em") > -1 &amp;&amp;
      !isNaN(Number(css_line_height_string.replace("em", "")))
    ) {
      css_line_height_string =
        Number(css_line_height_string.replace("em", "")) * 18.719 + "px";
    }
    if (
      css_line_height_string.indexOf("pt") > -1 &amp;&amp;
      !isNaN(Number(css_line_height_string.replace("pt", "")))
    ) {
      css_line_height_string =
        Number(css_line_height_string.replace("pt", "")) * 1.333 + "px";
    }

    var normal, undef, value;
    undef = void 0;
    normal = 16.0;
    value = UnitedNumberMap[css_line_height_string];
    if (value) {
      return value;
    }
    value = {
      "xx-small": 9,
      "x-small": 11,
      small: 13,
      medium: 16,
      large: 19,
      "x-large": 23,
      "xx-large": 28,
      auto: 0
    }[css_line_height_string];

    if (value !== undef) {
      return (UnitedNumberMap[css_line_height_string] = value / normal);
    }
    if ((value = parseFloat(css_line_height_string))) {
      return (UnitedNumberMap[css_line_height_string] = value / normal);
    }
    value = css_line_height_string.match(/([\d\.]+)(px)/);
    if (Array.isArray(value) &amp;&amp; value.length === 3) {
      return (UnitedNumberMap[css_line_height_string] =
        parseFloat(value[1]) / normal);
    }
    return (UnitedNumberMap[css_line_height_string] = 1);
  };
  GetCSS = function(element) {
    var css, tmp, computedCSSElement;
    computedCSSElement = (function(el) {
      var compCSS;
      compCSS = (function(el) {
        if (document.defaultView &amp;&amp; document.defaultView.getComputedStyle) {
          return document.defaultView.getComputedStyle(el, null);
        } else if (el.currentStyle) {
          return el.currentStyle;
        } else {
          return el.style;
        }
      })(el);
      return function(prop) {
        prop = prop.replace(/-\D/g, function(match) {
          return match.charAt(1).toUpperCase();
        });
        return compCSS[prop];
      };
    })(element);
    css = {};
    tmp = void 0;
    css["font-family"] =
      ResolveFont(computedCSSElement("font-family")) || "times";
    css["font-style"] =
      FontStyleMap[computedCSSElement("font-style")] || "normal";
    css["text-align"] =
      TextAlignMap[computedCSSElement("text-align")] || "left";
    tmp = FontWeightMap[computedCSSElement("font-weight")] || "normal";
    if (tmp === "bold") {
      if (css["font-style"] === "normal") {
        css["font-style"] = tmp;
      } else {
        css["font-style"] = tmp + css["font-style"];
      }
    }
    css["font-size"] =
      ResolveUnitedNumber(computedCSSElement("font-size")) || 1;
    css["line-height"] =
      ResolveUnitedNumber(computedCSSElement("line-height")) || 1;
    css["display"] =
      computedCSSElement("display") === "inline" ? "inline" : "block";

    tmp = css["display"] === "block";
    css["margin-top"] =
      (tmp &amp;&amp; ResolveUnitedNumber(computedCSSElement("margin-top"))) || 0;
    css["margin-bottom"] =
      (tmp &amp;&amp; ResolveUnitedNumber(computedCSSElement("margin-bottom"))) || 0;
    css["padding-top"] =
      (tmp &amp;&amp; ResolveUnitedNumber(computedCSSElement("padding-top"))) || 0;
    css["padding-bottom"] =
      (tmp &amp;&amp; ResolveUnitedNumber(computedCSSElement("padding-bottom"))) || 0;
    css["margin-left"] =
      (tmp &amp;&amp; ResolveUnitedNumber(computedCSSElement("margin-left"))) || 0;
    css["margin-right"] =
      (tmp &amp;&amp; ResolveUnitedNumber(computedCSSElement("margin-right"))) || 0;
    css["padding-left"] =
      (tmp &amp;&amp; ResolveUnitedNumber(computedCSSElement("padding-left"))) || 0;
    css["padding-right"] =
      (tmp &amp;&amp; ResolveUnitedNumber(computedCSSElement("padding-right"))) || 0;

    css["page-break-before"] =
      computedCSSElement("page-break-before") || "auto";

    //float and clearing of floats
    css["float"] = FloatMap[computedCSSElement("cssFloat")] || "none";
    css["clear"] = ClearMap[computedCSSElement("clear")] || "none";

    css["color"] = computedCSSElement("color");

    return css;
  };
  elementHandledElsewhere = function(element, renderer, elementHandlers) {
    var handlers, i, isHandledElsewhere, l, classNames, t;
    isHandledElsewhere = false;
    i = void 0;
    l = void 0;
    t = void 0;
    handlers = elementHandlers["#" + element.id];
    if (handlers) {
      if (typeof handlers === "function") {
        isHandledElsewhere = handlers(element, renderer);
      } else {
        i = 0;
        l = handlers.length;
        while (!isHandledElsewhere &amp;&amp; i !== l) {
          isHandledElsewhere = handlers[i](element, renderer);
          i++;
        }
      }
    }
    handlers = elementHandlers[element.nodeName];
    if (!isHandledElsewhere &amp;&amp; handlers) {
      if (typeof handlers === "function") {
        isHandledElsewhere = handlers(element, renderer);
      } else {
        i = 0;
        l = handlers.length;
        while (!isHandledElsewhere &amp;&amp; i !== l) {
          isHandledElsewhere = handlers[i](element, renderer);
          i++;
        }
      }
    }

    // Try class names
    classNames =
      typeof element.className === "string" ? element.className.split(" ") : [];
    for (i = 0; i &lt; classNames.length; i++) {
      handlers = elementHandlers["." + classNames[i]];
      if (!isHandledElsewhere &amp;&amp; handlers) {
        if (typeof handlers === "function") {
          isHandledElsewhere = handlers(element, renderer);
        } else {
          i = 0;
          l = handlers.length;
          while (!isHandledElsewhere &amp;&amp; i !== l) {
            isHandledElsewhere = handlers[i](element, renderer);
            i++;
          }
        }
      }
    }

    return isHandledElsewhere;
  };
  tableToJson = function(table, renderer) {
    var data, headers, i, j, rowData, tableRow, table_with, cell, l;
    data = [];
    headers = [];
    i = 0;
    l = table.rows[0].cells.length;
    table_with = table.clientWidth;
    while (i &lt; l) {
      cell = table.rows[0].cells[i];
      headers[i] = {
        name: cell.textContent.toLowerCase().replace(/\s+/g, ""),
        prompt: cell.textContent.replace(/\r?\n/g, ""),
        width:
          (cell.clientWidth / table_with) *
          renderer.pdf.internal.pageSize.getWidth()
      };
      i++;
    }
    i = 1;
    while (i &lt; table.rows.length) {
      tableRow = table.rows[i];
      rowData = {};
      j = 0;
      while (j &lt; tableRow.cells.length) {
        rowData[headers[j].name] = tableRow.cells[j].textContent.replace(
          /\r?\n/g,
          ""
        );
        j++;
      }
      data.push(rowData);
      i++;
    }
    return {
      rows: data,
      headers: headers
    };
  };
  var SkipNode = {
    SCRIPT: 1,
    STYLE: 1,
    NOSCRIPT: 1,
    OBJECT: 1,
    EMBED: 1,
    SELECT: 1
  };
  var listCount = 1;
  DrillForContent = function(element, renderer, elementHandlers) {
    var cn, cns, fragmentCSS, i, isBlock, l, table2json, cb;
    cns = element.childNodes;
    cn = void 0;
    fragmentCSS = GetCSS(element);
    isBlock = fragmentCSS.display === "block";
    if (isBlock) {
      renderer.setBlockBoundary();
      renderer.setBlockStyle(fragmentCSS);
    }
    i = 0;
    l = cns.length;
    while (i &lt; l) {
      cn = cns[i];
      if (typeof cn === "object") {
        //execute all watcher functions to e.g. reset floating
        renderer.executeWatchFunctions(cn);

        /*** HEADER rendering **/
        if (cn.nodeType === 1 &amp;&amp; cn.nodeName === "HEADER") {
          var header = cn;
          //store old top margin
          var oldMarginTop = renderer.pdf.margins_doc.top;
          //subscribe for new page event and render header first on every page
          renderer.pdf.internal.events.subscribe(
            "addPage",
            function(pageInfo) {
              //set current y position to old margin
              renderer.y = oldMarginTop;
              //render all child nodes of the header element
              DrillForContent(header, renderer, elementHandlers);
              //set margin to old margin + rendered header + 10 space to prevent overlapping
              //important for other plugins (e.g. table) to start rendering at correct position after header
              renderer.pdf.margins_doc.top = renderer.y + 10;
              renderer.y += 10;
            },
            false
          );
        }

        if (cn.nodeType === 8 &amp;&amp; cn.nodeName === "#comment") {
          if (~cn.textContent.indexOf("ADD_PAGE")) {
            renderer.pdf.addPage();
            renderer.y = renderer.pdf.margins_doc.top;
          }
        } else if (cn.nodeType === 1 &amp;&amp; !SkipNode[cn.nodeName]) {
          /*** IMAGE RENDERING ***/
          var cached_image;
          if (cn.nodeName === "IMG") {
            var url = cn.getAttribute("src");
            cached_image =
              images[renderer.pdf.API.__addimage__.sHashCode(url) || url];
          }
          if (cached_image) {
            if (
              renderer.pdf.internal.pageSize.getHeight() -
                renderer.pdf.margins_doc.bottom &lt;
                renderer.y + cn.height &amp;&amp;
              renderer.y > renderer.pdf.margins_doc.top
            ) {
              renderer.pdf.addPage();
              renderer.y = renderer.pdf.margins_doc.top;
              //check if we have to set back some values due to e.g. header rendering for new page
              renderer.executeWatchFunctions(cn);
            }

            var imagesCSS = GetCSS(cn);
            var imageX = renderer.x;
            var fontToUnitRatio = 12 / renderer.pdf.internal.scaleFactor;

            //define additional paddings, margins which have to be taken into account for margin calculations
            var additionalSpaceLeft =
              (imagesCSS["margin-left"] + imagesCSS["padding-left"]) *
              fontToUnitRatio;
            var additionalSpaceRight =
              (imagesCSS["margin-right"] + imagesCSS["padding-right"]) *
              fontToUnitRatio;
            var additionalSpaceTop =
              (imagesCSS["margin-top"] + imagesCSS["padding-top"]) *
              fontToUnitRatio;
            var additionalSpaceBottom =
              (imagesCSS["margin-bottom"] + imagesCSS["padding-bottom"]) *
              fontToUnitRatio;

            //if float is set to right, move the image to the right border
            //add space if margin is set
            if (
              imagesCSS["float"] !== undefined &amp;&amp;
              imagesCSS["float"] === "right"
            ) {
              imageX +=
                renderer.settings.width - cn.width - additionalSpaceRight;
            } else {
              imageX += additionalSpaceLeft;
            }

            renderer.pdf.addImage(
              cached_image,
              imageX,
              renderer.y + additionalSpaceTop,
              cn.width,
              cn.height
            );
            cached_image = undefined;
            //if the float prop is specified we have to float the text around the image
            if (
              imagesCSS["float"] === "right" ||
              imagesCSS["float"] === "left"
            ) {
              //add functiont to set back coordinates after image rendering
              renderer.watchFunctions.push(
                function(diffX, thresholdY, diffWidth, el) {
                  //undo drawing box adaptions which were set by floating
                  if (renderer.y >= thresholdY) {
                    renderer.x += diffX;
                    renderer.settings.width += diffWidth;
                    return true;
                  } else if (
                    el &amp;&amp;
                    el.nodeType === 1 &amp;&amp;
                    !SkipNode[el.nodeName] &amp;&amp;
                    renderer.x + el.width >
                      renderer.pdf.margins_doc.left +
                        renderer.pdf.margins_doc.width
                  ) {
                    renderer.x += diffX;
                    renderer.y = thresholdY;
                    renderer.settings.width += diffWidth;
                    return true;
                  } else {
                    return false;
                  }
                }.bind(
                  this,
                  imagesCSS["float"] === "left"
                    ? -cn.width - additionalSpaceLeft - additionalSpaceRight
                    : 0,
                  renderer.y +
                    cn.height +
                    additionalSpaceTop +
                    additionalSpaceBottom,
                  cn.width
                )
              );
              //reset floating by clear:both divs
              //just set cursorY after the floating element
              renderer.watchFunctions.push(
                function(yPositionAfterFloating, pages, el) {
                  if (
                    renderer.y &lt; yPositionAfterFloating &amp;&amp;
                    pages === renderer.pdf.internal.getNumberOfPages()
                  ) {
                    if (el.nodeType === 1 &amp;&amp; GetCSS(el).clear === "both") {
                      renderer.y = yPositionAfterFloating;
                      return true;
                    } else {
                      return false;
                    }
                  } else {
                    return true;
                  }
                }.bind(
                  this,
                  renderer.y + cn.height,
                  renderer.pdf.internal.getNumberOfPages()
                )
              );

              //if floating is set we decrease the available width by the image width
              renderer.settings.width -=
                cn.width + additionalSpaceLeft + additionalSpaceRight;
              //if left just add the image width to the X coordinate
              if (imagesCSS["float"] === "left") {
                renderer.x +=
                  cn.width + additionalSpaceLeft + additionalSpaceRight;
              }
            } else {
              //if no floating is set, move the rendering cursor after the image height
              renderer.y +=
                cn.height + additionalSpaceTop + additionalSpaceBottom;
            }

            /*** TABLE RENDERING ***/
          } else if (cn.nodeName === "TABLE") {
            table2json = tableToJson(cn, renderer);
            renderer.y += 10;
            renderer.pdf.table(
              renderer.x,
              renderer.y,
              table2json.rows,
              table2json.headers,
              {
                autoSize: false,
                printHeaders: elementHandlers.printHeaders,
                margins: renderer.pdf.margins_doc,
                css: GetCSS(cn)
              }
            );
            renderer.y =
              renderer.pdf.lastCellPos.y + renderer.pdf.lastCellPos.h + 20;
          } else if (cn.nodeName === "OL" || cn.nodeName === "UL") {
            listCount = 1;
            if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
              DrillForContent(cn, renderer, elementHandlers);
            }
            renderer.y += 10;
          } else if (cn.nodeName === "LI") {
            var temp = renderer.x;
            renderer.x += 20 / renderer.pdf.internal.scaleFactor;
            renderer.y += 3;
            if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
              DrillForContent(cn, renderer, elementHandlers);
            }
            renderer.x = temp;
          } else if (cn.nodeName === "BR") {
            renderer.y +=
              fragmentCSS["font-size"] * renderer.pdf.internal.scaleFactor;
            renderer.addText("\u2028", clone(fragmentCSS));
          } else {
            if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
              DrillForContent(cn, renderer, elementHandlers);
            }
          }
        } else if (cn.nodeType === 3) {
          var value = cn.nodeValue;
          if (cn.nodeValue &amp;&amp; cn.parentNode.nodeName === "LI") {
            if (cn.parentNode.parentNode.nodeName === "OL") {
              value = listCount++ + ". " + value;
            } else {
              var fontSize = fragmentCSS["font-size"];
              var offsetX =
                (3 - fontSize * 0.75) * renderer.pdf.internal.scaleFactor;
              var offsetY = fontSize * 0.75 * renderer.pdf.internal.scaleFactor;
              var radius =
                (fontSize * 1.74) / renderer.pdf.internal.scaleFactor;
              cb = function(x, y) {
                this.pdf.circle(x + offsetX, y + offsetY, radius, "FD");
              };
            }
          }
          // Only add the text if the text node is in the body element
          // Add compatibility with IE11
          if (!!(cn.ownerDocument.body.compareDocumentPosition(cn) &amp; 16)) {
            renderer.addText(value, fragmentCSS);
          }
        } else if (typeof cn === "string") {
          renderer.addText(cn, fragmentCSS);
        }
      }
      i++;
    }
    elementHandlers.outY = renderer.y;

    if (isBlock) {
      return renderer.setBlockBoundary(cb);
    }
  };
  images = {};
  loadImgs = function(element, renderer, elementHandlers, cb) {
    var imgs = element.getElementsByTagName("img"),
      l = imgs.length,
      found_images,
      x = 0;
    function done() {
      renderer.pdf.internal.events.publish("imagesLoaded");
      cb(found_images);
    }
    function loadImage(url, width, height) {
      if (!url) return;
      var img = new Image();
      found_images = ++x;
      img.crossOrigin = "";
      img.onerror = img.onload = function() {
        if (img.complete) {
          //to support data urls in images, set width and height
          //as those values are not recognized automatically
          if (img.src.indexOf("data:image/") === 0) {
            img.width = width || img.width || 0;
            img.height = height || img.height || 0;
          }
          //if valid image add to known images array
          if (img.width + img.height) {
            var hash = renderer.pdf.API.__addimage__.sHashCode(url) || url;
            images[hash] = images[hash] || img;
          }
        }
        if (!--x) {
          done();
        }
      };
      img.src = url;
    }
    while (l--)
      loadImage(imgs[l].getAttribute("src"), imgs[l].width, imgs[l].height);
    return x || done();
  };
  checkForFooter = function(elem, renderer, elementHandlers) {
    //check if we can found a &lt;footer> element
    var footer = elem.getElementsByTagName("footer");
    if (footer.length > 0) {
      footer = footer[0];

      //bad hack to get height of footer
      //creat dummy out and check new y after fake rendering
      var oldOut = renderer.pdf.internal.write;
      var oldY = renderer.y;
      renderer.pdf.internal.write = function() {};
      DrillForContent(footer, renderer, elementHandlers);
      var footerHeight = Math.ceil(renderer.y - oldY) + 5;
      renderer.y = oldY;
      renderer.pdf.internal.write = oldOut;

      //add 20% to prevent overlapping
      renderer.pdf.margins_doc.bottom += footerHeight;

      //Create function render header on every page
      var renderFooter = function(pageInfo) {
        var pageNumber = pageInfo !== undefined ? pageInfo.pageNumber : 1;
        //set current y position to old margin
        var oldPosition = renderer.y;
        //render all child nodes of the header element
        renderer.y =
          renderer.pdf.internal.pageSize.getHeight() -
          renderer.pdf.margins_doc.bottom;
        renderer.pdf.margins_doc.bottom -= footerHeight;

        //check if we have to add page numbers
        var spans = footer.getElementsByTagName("span");
        for (var i = 0; i &lt; spans.length; ++i) {
          //if we find some span element with class pageCounter, set the page
          if (
            (" " + spans[i].className + " ")
              .replace(/[\n\t]/g, " ")
              .indexOf(" pageCounter ") > -1
          ) {
            spans[i].innerHTML = pageNumber;
          }
          //if we find some span element with class totalPages, set a variable which is replaced after rendering of all pages
          if (
            (" " + spans[i].className + " ")
              .replace(/[\n\t]/g, " ")
              .indexOf(" totalPages ") > -1
          ) {
            spans[i].innerHTML = "###jsPDFVarTotalPages###";
          }
        }

        //render footer content
        DrillForContent(footer, renderer, elementHandlers);
        //set bottom margin to previous height including the footer height
        renderer.pdf.margins_doc.bottom += footerHeight;
        //important for other plugins (e.g. table) to start rendering at correct position after header
        renderer.y = oldPosition;
      };

      //check if footer contains totalPages which should be replace at the disoposal of the document
      var spans = footer.getElementsByTagName("span");
      for (var i = 0; i &lt; spans.length; ++i) {
        if (
          (" " + spans[i].className + " ")
            .replace(/[\n\t]/g, " ")
            .indexOf(" totalPages ") > -1
        ) {
          renderer.pdf.internal.events.subscribe(
            "htmlRenderingFinished",
            renderer.pdf.putTotalPages.bind(
              renderer.pdf,
              "###jsPDFVarTotalPages###"
            ),
            true
          );
        }
      }

      //register event to render footer on every new page
      renderer.pdf.internal.events.subscribe("addPage", renderFooter, false);
      //render footer on first page
      renderFooter();

      //prevent footer rendering
      SkipNode["FOOTER"] = 1;
    }
  };
  process = function(pdf, element, x, y, settings, callback) {
    if (!element) return false;
    if (typeof element !== "string" &amp;&amp; !element.parentNode)
      element = "" + element.innerHTML;
    if (typeof element === "string") {
      element = (function(element) {
        var $frame, $hiddendiv, framename, visuallyhidden;
        framename =
          "jsPDFhtmlText" +
          Date.now().toString() +
          (Math.random() * 1000).toFixed(0);
        visuallyhidden =
          "position: absolute !important;" +
          "clip: rect(1px 1px 1px 1px); /* IE6, IE7 */" +
          "clip: rect(1px, 1px, 1px, 1px);" +
          "padding:0 !important;" +
          "border:0 !important;" +
          "height: 1px !important;" +
          "width: 1px !important; " +
          "top:auto;" +
          "left:-100px;" +
          "overflow: hidden;";
        $hiddendiv = document.createElement("div");
        $hiddendiv.style.cssText = visuallyhidden;
        $hiddendiv.innerHTML =
          '&lt;iframe style="height:1px;width:1px" name="' + framename + '" />';
        document.body.appendChild($hiddendiv);
        $frame = window.frames[framename];
        $frame.document.open();
        $frame.document.writeln(element);
        $frame.document.close();
        return $frame.document.body;
      })(element.replace(/&lt;\/?script[^>]*?>/gi, ""));
    }
    var r = new Renderer(pdf, x, y, settings),
      out;

    // 1. load images
    // 2. prepare optional footer elements
    // 3. render content
    loadImgs.call(this, element, r, settings.elementHandlers, function(
      found_images
    ) {
      checkForFooter(element, r, settings.elementHandlers);
      DrillForContent(element, r, settings.elementHandlers);
      //send event dispose for final taks (e.g. footer totalpage replacement)
      r.pdf.internal.events.publish("htmlRenderingFinished");
      out = r.dispose();
      if (typeof callback === "function") callback(out);
      else if (found_images)
        console.error(
          "jsPDF Warning: rendering issues? provide a callback to fromHTML!"
        );
    });
    return out || { x: r.x, y: r.y };
  };
  Renderer.prototype.init = function() {
    this.paragraph = {
      text: [],
      style: []
    };
    return this.pdf.internal.write("q");
  };
  Renderer.prototype.dispose = function() {
    this.pdf.internal.write("Q");
    return {
      x: this.x,
      y: this.y,
      ready: true
    };
  };

  //Checks if we have to execute some watcher functions
  //e.g. to end text floating around an image
  Renderer.prototype.executeWatchFunctions = function(el) {
    var ret = false;
    var narray = [];
    if (this.watchFunctions.length > 0) {
      for (var i = 0; i &lt; this.watchFunctions.length; ++i) {
        if (this.watchFunctions[i](el) === true) {
          ret = true;
        } else {
          narray.push(this.watchFunctions[i]);
        }
      }
      this.watchFunctions = narray;
    }
    return ret;
  };

  Renderer.prototype.splitFragmentsIntoLines = function(fragments, styles) {
    var currentLineLength,
      defaultFontSize,
      ff,
      fontMetrics,
      fontMetricsCache,
      fragment,
      fragmentChopped,
      fragmentLength,
      fragmentSpecificMetrics,
      fs,
      k,
      line,
      lines,
      maxLineLength,
      style;
    defaultFontSize = 12;
    k = this.pdf.internal.scaleFactor;
    fontMetricsCache = {};
    ff = void 0;
    fs = void 0;
    fontMetrics = void 0;
    fragment = void 0;
    style = void 0;
    fragmentSpecificMetrics = void 0;
    fragmentLength = void 0;
    fragmentChopped = void 0;
    line = [];
    lines = [line];
    currentLineLength = 0;
    maxLineLength = this.settings.width;
    while (fragments.length) {
      fragment = fragments.shift();
      style = styles.shift();
      if (fragment) {
        ff = style["font-family"];
        fs = style["font-style"];
        fontMetrics = fontMetricsCache[ff + fs];
        if (!fontMetrics) {
          fontMetrics = this.pdf.internal.getFont(ff, fs).metadata.Unicode;
          fontMetricsCache[ff + fs] = fontMetrics;
        }
        fragmentSpecificMetrics = {
          widths: fontMetrics.widths,
          kerning: fontMetrics.kerning,
          fontSize: style["font-size"] * defaultFontSize,
          textIndent: currentLineLength
        };
        fragmentLength =
          (this.pdf.getStringUnitWidth(fragment, fragmentSpecificMetrics) *
            fragmentSpecificMetrics.fontSize) /
          k;
        if (fragment == "\u2028") {
          line = [];
          lines.push(line);
        } else if (currentLineLength + fragmentLength > maxLineLength) {
          fragmentChopped = this.pdf.splitTextToSize(
            fragment,
            maxLineLength,
            fragmentSpecificMetrics
          );
          line.push([fragmentChopped.shift(), style]);
          while (fragmentChopped.length) {
            line = [[fragmentChopped.shift(), style]];
            lines.push(line);
          }
          currentLineLength =
            (this.pdf.getStringUnitWidth(line[0][0], fragmentSpecificMetrics) *
              fragmentSpecificMetrics.fontSize) /
            k;
        } else {
          line.push([fragment, style]);
          currentLineLength += fragmentLength;
        }
      }
    }

    //if text alignment was set, set margin/indent of each line
    if (
      style["text-align"] !== undefined &amp;&amp;
      (style["text-align"] === "center" ||
        style["text-align"] === "right" ||
        style["text-align"] === "justify")
    ) {
      for (var i = 0; i &lt; lines.length; ++i) {
        var length =
          (this.pdf.getStringUnitWidth(
            lines[i][0][0],
            fragmentSpecificMetrics
          ) *
            fragmentSpecificMetrics.fontSize) /
          k;
        //if there is more than on line we have to clone the style object as all lines hold a reference on this object
        if (i > 0) {
          lines[i][0][1] = clone(lines[i][0][1]);
        }
        var space = maxLineLength - length;

        if (style["text-align"] === "right") {
          lines[i][0][1]["margin-left"] = space;
          //if alignment is not right, it has to be center so split the space to the left and the right
        } else if (style["text-align"] === "center") {
          lines[i][0][1]["margin-left"] = space / 2;
          //if justify was set, calculate the word spacing and define in by using the css property
        } else if (style["text-align"] === "justify") {
          var countSpaces = lines[i][0][0].split(" ").length - 1;
          lines[i][0][1]["word-spacing"] = space / countSpaces;
          //ignore the last line in justify mode
          if (i === lines.length - 1) {
            lines[i][0][1]["word-spacing"] = 0;
          }
        }
      }
    }

    return lines;
  };
  Renderer.prototype.RenderTextFragment = function(text, style) {
    var defaultFontSize, font, maxLineHeight;

    maxLineHeight = 0;
    defaultFontSize = 12;

    if (
      this.pdf.internal.pageSize.getHeight() - this.pdf.margins_doc.bottom &lt;
      this.y + this.pdf.internal.getFontSize()
    ) {
      this.pdf.internal.write("ET", "Q");
      this.pdf.addPage();
      this.y = this.pdf.margins_doc.top;
      this.pdf.internal.write(
        "q",
        "BT",
        this.getPdfColor(style.color),
        this.pdf.internal.getCoordinateString(this.x),
        this.pdf.internal.getVerticalCoordinateString(this.y),
        "Td"
      );
      //move cursor by one line on new page
      maxLineHeight = Math.max(
        maxLineHeight,
        style["line-height"],
        style["font-size"]
      );
      this.pdf.internal.write(
        0,
        (-1 * defaultFontSize * maxLineHeight).toFixed(2),
        "Td"
      );
    }

    font = this.pdf.internal.getFont(style["font-family"], style["font-style"]);

    // text color
    var pdfTextColor = this.getPdfColor(style["color"]);
    if (pdfTextColor !== this.lastTextColor) {
      this.pdf.internal.write(pdfTextColor);
      this.lastTextColor = pdfTextColor;
    }

    //set the word spacing for e.g. justify style
    if (style["word-spacing"] !== undefined &amp;&amp; style["word-spacing"] > 0) {
      this.pdf.internal.write(style["word-spacing"].toFixed(2), "Tw");
    }

    this.pdf.internal.write(
      "/" + font.id,
      (defaultFontSize * style["font-size"]).toFixed(2),
      "Tf",
      "(" + this.pdf.internal.pdfEscape(text) + ") Tj"
    );

    //set the word spacing back to neutral => 0
    if (style["word-spacing"] !== undefined) {
      this.pdf.internal.write(0, "Tw");
    }
  };

  // Accepts #FFFFFF, rgb(int,int,int), or CSS Color Name
  Renderer.prototype.getPdfColor = function(style) {
    var textColor;
    var r, g, b;

    var rx = /rgb\s*\(\s*(\d+),\s*(\d+),\s*(\d+\s*)\)/;
    var m = rx.exec(style);
    if (m != null) {
      r = parseInt(m[1]);
      g = parseInt(m[2]);
      b = parseInt(m[3]);
    } else {
      if (typeof style === "string" &amp;&amp; style.charAt(0) != "#") {
        var rgbColor = new RGBColor(style);
        if (rgbColor.ok) {
          style = rgbColor.toHex();
        } else {
          style = "#000000";
        }
      }
      r = style.substring(1, 3);
      r = parseInt(r, 16);
      g = style.substring(3, 5);
      g = parseInt(g, 16);
      b = style.substring(5, 7);
      b = parseInt(b, 16);
    }

    if (typeof r === "string" &amp;&amp; /^#[0-9A-Fa-f]{6}$/.test(r)) {
      var hex = parseInt(r.substr(1), 16);
      r = (hex >> 16) &amp; 255;
      g = (hex >> 8) &amp; 255;
      b = hex &amp; 255;
    }

    var f3 = this.f3;
    if ((r === 0 &amp;&amp; g === 0 &amp;&amp; b === 0) || typeof g === "undefined") {
      textColor = f3(r / 255) + " g";
    } else {
      textColor = [f3(r / 255), f3(g / 255), f3(b / 255), "rg"].join(" ");
    }
    return textColor;
  };

  (Renderer.prototype.f3 = function(number) {
    return number.toFixed(3); // Ie, %.3f
  }),
    (Renderer.prototype.renderParagraph = function(cb) {
      var blockstyle,
        defaultFontSize,
        fontToUnitRatio,
        fragments,
        i,
        l,
        line,
        lines,
        maxLineHeight,
        out,
        paragraphspacing_after,
        paragraphspacing_before,
        styles,
        fontSize;
      fragments = PurgeWhiteSpace(this.paragraph.text);
      styles = this.paragraph.style;
      blockstyle = this.paragraph.blockstyle;
      this.paragraph = {
        text: [],
        style: [],
        blockstyle: {},
        priorblockstyle: blockstyle
      };
      if (!fragments.join("").trim()) {
        return;
      }
      lines = this.splitFragmentsIntoLines(fragments, styles);
      line = void 0;
      maxLineHeight = void 0;
      defaultFontSize = 12;
      fontToUnitRatio = defaultFontSize / this.pdf.internal.scaleFactor;
      this.priorMarginBottom = this.priorMarginBottom || 0;
      paragraphspacing_before =
        (Math.max((blockstyle["margin-top"] || 0) - this.priorMarginBottom, 0) +
          (blockstyle["padding-top"] || 0)) *
        fontToUnitRatio;
      paragraphspacing_after =
        ((blockstyle["margin-bottom"] || 0) +
          (blockstyle["padding-bottom"] || 0)) *
        fontToUnitRatio;
      this.priorMarginBottom = blockstyle["margin-bottom"] || 0;

      if (blockstyle["page-break-before"] === "always") {
        this.pdf.addPage();
        this.y = 0;
        paragraphspacing_before =
          ((blockstyle["margin-top"] || 0) + (blockstyle["padding-top"] || 0)) *
          fontToUnitRatio;
      }

      out = this.pdf.internal.write;
      i = void 0;
      l = void 0;
      this.y += paragraphspacing_before;
      out(
        "q",
        "BT 0 g",
        this.pdf.internal.getCoordinateString(this.x),
        this.pdf.internal.getVerticalCoordinateString(this.y),
        "Td"
      );

      //stores the current indent of cursor position
      var currentIndent = 0;

      while (lines.length) {
        line = lines.shift();
        maxLineHeight = 0;
        i = 0;
        l = line.length;
        while (i !== l) {
          if (line[i][0].trim()) {
            maxLineHeight = Math.max(
              maxLineHeight,
              line[i][1]["line-height"],
              line[i][1]["font-size"]
            );
            fontSize = line[i][1]["font-size"] * 7;
          }
          i++;
        }
        //if we have to move the cursor to adapt the indent
        var indentMove = 0;
        var wantedIndent = 0;
        //if a margin was added (by e.g. a text-alignment), move the cursor
        if (
          line[0][1]["margin-left"] !== undefined &amp;&amp;
          line[0][1]["margin-left"] > 0
        ) {
          wantedIndent = this.pdf.internal.getCoordinateString(
            line[0][1]["margin-left"]
          );
          indentMove = wantedIndent - currentIndent;
          currentIndent = wantedIndent;
        }
        var indentMore =
          Math.max(blockstyle["margin-left"] || 0, 0) * fontToUnitRatio;
        //move the cursor
        out(
          indentMove + indentMore,
          (-1 * defaultFontSize * maxLineHeight).toFixed(2),
          "Td"
        );
        i = 0;
        l = line.length;
        while (i !== l) {
          if (line[i][0]) {
            this.RenderTextFragment(line[i][0], line[i][1]);
          }
          i++;
        }
        this.y += maxLineHeight * fontToUnitRatio;

        //if some watcher function was executed successful, so e.g. margin and widths were changed,
        //reset line drawing and calculate position and lines again
        //e.g. to stop text floating around an image
        if (this.executeWatchFunctions(line[0][1]) &amp;&amp; lines.length > 0) {
          var localFragments = [];
          var localStyles = [];
          //create fragment array of
          lines.forEach(function(localLine) {
            var i = 0;
            var l = localLine.length;
            while (i !== l) {
              if (localLine[i][0]) {
                localFragments.push(localLine[i][0] + " ");
                localStyles.push(localLine[i][1]);
              }
              ++i;
            }
          });
          //split lines again due to possible coordinate changes
          lines = this.splitFragmentsIntoLines(
            PurgeWhiteSpace(localFragments),
            localStyles
          );
          //reposition the current cursor
          out("ET", "Q");
          out(
            "q",
            "BT 0 g",
            this.pdf.internal.getCoordinateString(this.x),
            this.pdf.internal.getVerticalCoordinateString(this.y),
            "Td"
          );
        }
      }
      if (cb &amp;&amp; typeof cb === "function") {
        cb.call(this, this.x - 9, this.y - fontSize / 2);
      }
      out("ET", "Q");
      return (this.y += paragraphspacing_after);
    });
  Renderer.prototype.setBlockBoundary = function(cb) {
    return this.renderParagraph(cb);
  };
  Renderer.prototype.setBlockStyle = function(css) {
    return (this.paragraph.blockstyle = css);
  };
  Renderer.prototype.addText = function(text, css) {
    this.paragraph.text.push(text);
    return this.paragraph.style.push(css);
  };
  FontNameDB = {
    helvetica: "helvetica",
    "sans-serif": "helvetica",
    "times new roman": "times",
    serif: "times",
    times: "times",
    monospace: "courier",
    courier: "courier"
  };
  FontWeightMap = {
    100: "normal",
    200: "normal",
    300: "normal",
    400: "normal",
    500: "bold",
    600: "bold",
    700: "bold",
    800: "bold",
    900: "bold",
    normal: "normal",
    bold: "bold",
    bolder: "bold",
    lighter: "normal"
  };
  FontStyleMap = {
    normal: "normal",
    italic: "italic",
    oblique: "italic"
  };
  TextAlignMap = {
    left: "left",
    right: "right",
    center: "center",
    justify: "justify"
  };
  FloatMap = {
    none: "none",
    right: "right",
    left: "left"
  };
  ClearMap = {
    none: "none",
    both: "both"
  };
  UnitedNumberMap = {
    normal: 1
  };
  /**
   * Converts HTML-formatted text into formatted PDF text.
   *
   * Notes:
   * 2012-07-18
   * Plugin relies on having browser, DOM around. The HTML is pushed into dom and traversed.
   * Plugin relies on jQuery for CSS extraction.
   * Targeting HTML output from Markdown templating, which is a very simple
   * markup - div, span, em, strong, p. No br-based paragraph separation supported explicitly (but still may work.)
   * Images, tables are NOT supported.
   *
   * @public
   * @function
   * @param HTML {String|Object} HTML-formatted text, or pointer to DOM element that is to be rendered into PDF.
   * @param x {Number} starting X coordinate in jsPDF instance's declared units.
   * @param y {Number} starting Y coordinate in jsPDF instance's declared units.
   * @param settings {Object} Additional / optional variables controlling parsing, rendering.
   * @returns {Object} jsPDF instance
   */
  jsPDFAPI.fromHTML = function(HTML, x, y, settings, callback, margins) {
    "use strict";

    this.margins_doc = margins || {
      top: 0,
      bottom: 0
    };
    if (!settings) settings = {};
    if (!settings.elementHandlers) settings.elementHandlers = {};

    return process(
      this,
      HTML,
      isNaN(x) ? 4 : x,
      isNaN(y) ? 4 : y,
      settings,
      callback
    );
  };
})(jsPDF.API);
</code></pre>
        </article>
    </section>




    
    
</div>

<br class="clear">

<footer>
    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.0</a> on Wed Aug 07 2019 10:12:05 GMT+0200 (W. Europe Daylight Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>

<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>



</body>
</html>
